Skip to content

Handle UuidToStringA failure in GenerateRuntimeId - #9026

Draft
link04 wants to merge 1 commit into
masterfrom
maximo/fix-uuidtostring-error-handling
Draft

Handle UuidToStringA failure in GenerateRuntimeId#9026
link04 wants to merge 1 commit into
masterfrom
maximo/fix-uuidtostring-error-handling

Conversation

@link04

@link04 link04 commented Aug 11, 2026

Copy link
Copy Markdown
Contributor

Summary of changes

GenerateRuntimeId ignored the return value of UuidToStringA and freed the output pointer unconditionally. Check it, and fall back to GenerateUuidV4() when it fails.

Reason for change

UuidToStringA returns RPC_S_OUT_OF_MEMORY on failure and leaves StringUuid untouched. str was uninitialised, so on that path we handed a garbage stack value to RpcStringFreeA. That reaches RtlFreeHeap with a pointer that was never a live heap block, and Windows treats it as STATUS_HEAP_CORRUPTION, which is a non-continuable fast-fail. The process dies immediately, with no chance to handle it.

This runs on essentially every instrumented .NET process start on Windows. RuntimeIdStore is a by-value member of the native loader's CorProfiler, so its constructor runs during CoCreateProfiler. A rare allocation failure inside RPC therefore becomes a hard kill of the customer's process rather than a degraded runtime id.

I found this while looking at a crash report with exactly that signature on 3.32.1: runtimeid_store.cpp:25 -> RpcStringFree -> RtlFreeHeap -> RtlpHeapHandleError -> RtlReportCriticalFailure. To be clear, I can't prove that report was caused by this rather than by heap corruption elsewhere in the process that this free happened to be the first to detect. The unchecked return value is wrong either way, so this is worth fixing on its own merits.

Implementation details

Initialise str, and return the existing GenerateUuidV4() fallback when UuidToStringA does not return RPC_S_OK. GenerateUuidV4 is already the non-Windows implementation, so there is no new code behind the fallback.

Not checking UuidCreate on purpose. RPC_S_UUID_LOCAL_ONLY still yields a usable UUID, and that result has no bearing on the free.

Test coverage

The existing runtimeid_store gtests only cover the success path. Covering the failure path needs a seam to inject the UuidToStringA result, which I left out to keep this small. Happy to add it if reviewers would rather have it.

I could not build this locally, so CI is the first compile check.

Other details

Windows only. Linux already went through GenerateUuidV4().

🤖 Generated with Claude Code

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
@dd-trace-dotnet-ci-bot

Copy link
Copy Markdown

Execution-Time Benchmarks Report ⏱️

Execution-time results for samples comparing This PR (9026) and master.

⚠️ Potential regressions detected

HttpMessageHandler

Metric Master (Mean ± 95% CI) Current (Mean ± 95% CI) Change Status
.NET Framework 4.8 - Baseline
duration190.44 ± (190.41 - 191.25) ms211.75 ± (211.51 - 212.43) ms+11.2%❌⬆️
.NET Framework 4.8 - Bailout
duration194.15 ± (194.07 - 194.52) ms217.89 ± (217.34 - 218.42) ms+12.2%❌⬆️
.NET Framework 4.8 - CallTarget+Inlining+NGEN
duration1168.63 ± (1168.89 - 1174.84) ms1293.36 ± (1291.05 - 1298.29) ms+10.7%❌⬆️

📄 View the full report (charts + all metrics) →

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant